<?php


namespace App\Services;

use App\Models\UploadFile;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;

class UploadService
{
    protected $ttl = 86400;

    public static function init()
    {
        return new  self();
    }

    /***
     * 文件上传
     * @param $file 二进制文件流
     * @param $from 来源。admin后台 | home 移动端
     * @param $uploaderId 上传者
     * @return array|string[]
     */
    public function upload($file, $type, $uploaderId)
    {
        //判断项目环境
        $environment = config('app.env');
        if ($environment == 'production') {
            $dir = 'production';
        } else {
            $dir = 'dev';
        }

        //文件加密值
        $md5 = md5_file($file);

        //根据md5查询文件
        $files = $this->getFileMd5ToRemoteUrl($md5);

        if ($files){
            return showData($files);
        } 

        //获取文件后缀
        $ext = $file->extension();

        //获取图片在临时文件中的地址
        $FilePath = $file->getRealPath();

        //制作文件名
        $object_name = $dir . '/' . md5(date('Ymd', time()) . uniqid()) . '.' . $ext;

        //开始上传
        $uploadFile = Storage::disk('oss')->put($object_name, file_get_contents($FilePath));
        if ($uploadFile) {
            $fileUrl = Storage::disk('oss')->url($object_name) ?? '';
            $model = new UploadFile;
            $model->local_url = parse_url($fileUrl, PHP_URL_PATH);
            $model->remote_url = parse_url($fileUrl, PHP_URL_PATH);
            $model->md5_value = $md5;
            $model->ext = $ext;
            $model->user_id = $uploaderId;
            $model->type = $type;
            $model->save();
            $this->setCacheFile($model->id, $model->md5_value, $model->local_url);
            return showData(['file_id' => $model->id, "remote_url" => $this->getRemoteUrlAttribute($model->local_url)]);
        }

        return showError('上传失败');
    }


    /**
     * @param $userId int 用户id
     * @param $headImgUrl string 用户微信头像地址
     */
    public function uploadHeadImg($userId, $headImgUrl)
    {
        //判断项目环境
        $environment = config('app.env');
        if ($environment == 'production') {
            $dir = 'production';
        } else {
            $dir = 'dev';
        }

        $ext = 'jpeg';
        $md5 = $dir . '/' . md5(time() . '/' . uniqid());

        // 制作文件名
        $object_name = $md5 . ".$ext";
        $file = Storage::disk('oss')->put($object_name, file_get_contents($headImgUrl));

        /*是否上传成功*/
        if (!$file) {
            return false;
        }

        $fileUrl = Storage::disk('oss')->url($object_name) ?? '';
        $model = new UploadFile;
        $model->local_url = parse_url($fileUrl, PHP_URL_PATH);
        $model->remote_url = parse_url($fileUrl, PHP_URL_PATH);
        $model->ext = $ext;
        $model->md5_value = $md5;
        $model->user_id = $userId;
        $model->save();
        $this->setCacheFile($model->id, $md5,  $this->getRemoteUrlAttribute($model->local_url));
        return ['file_id' => $model->id];
    }

    /***
     * 根据md5，把文件id写入
     * @param $file_id
     * @param $file_md5_value
     * @return bool
     */
    public function setCacheFileMd5($file_id, $file_md5_value)
    {
        $key = "file_md5:" . $file_md5_value;
        return Cache::put($key, $file_id, $this->ttl);
    }

    /***
     * 根据文件id写入文件地址
     * @param $file_id
     * @param $remote_url
     * @return bool
     */
    public function setCacheFileId($file_id, $remote_url)
    {
        $key = "file_id:" . $file_id;
        return Cache::put($key, $remote_url, $this->ttl);
    }

    /***
     * 把文件id、文件md5，文件地址写入缓存
     * @param $file_id
     * @param $file_md5_value
     * @param $remote_url
     * @return bool
     */
    public function setCacheFile($file_id, $file_md5_value, $remote_url)
    {
        $this->setCacheFileId($file_id, $remote_url);
        $this->setCacheFileMd5($file_id, $file_md5_value);
        return true;
    }

    /***
     * 根据文件id获取文件地址
     * @param $file_id
     * @return array|null
     */
    public function getFileIdToRemoteUrl($file_id)
    {
        $key = "file_id:" . $file_id;
        $local_url = Cache::get($key);

        if ($local_url) {
            return ['file_id' => $file_id, 'remote_url' => $this->getRemoteUrlAttribute($local_url)];
        }
        
        $data = null;
        if (!$local_url) {
            $file = UploadFile::query()->where('id', $file_id)->first();
            if ($file) {
                $this->setCacheFile($file_id, $file->md5_value, $file->local_url);
                $data = ['file_id' => $file_id, 'remote_url' => $this->getRemoteUrlAttribute($file->local_url)];
            }
        }
        return $data;
    }

    /***
     * 根据文件id获取文件地址
     * @param $file_id
     * @return array|null
     */
    public function getFileIdToRemoteUrlUser($file_id)
    {
        $key = "file_id:" . $file_id;
        $local_url = Cache::get($key);
        if ($local_url) {
            return ['file_id' => $file_id, 'remote_url' => $this->getRemoteUrlAttribute($local_url)];
        }
        $data = null;
        if (!$local_url) {
            $file = UploadFile::query()->where('id', $file_id)->with('user:id,nick_name')->first();
            if ($file) {
                $this->setCacheFile($file_id, $file->md5_value, $file->local_url);
                $data = [
                    'file_id' => $file_id,
                    'remote_url' => $this->getRemoteUrlAttribute($file->local_url),
                    'created_at' => $file->toArray()['created_at'],//时间格式错误，转为array解决
                    'user' => $file->user

                ];
            }
        }
        return $data;
    }

    /***
     * 根据md5获取文件
     * @param $file_md5_value
     * @return array|null
     */
    public function getFileMd5ToRemoteUrl($file_md5_value)
    {
        $key = "file_md5:" . $file_md5_value;

        $file_id = Cache::get($key);

        if ($file_id) {
            return $this->getFileIdToRemoteUrl($file_id);
        }

        $data = null;
        if (!$file_id) {
            $file = UploadFile::query()->where('md5_value', $file_md5_value)->first();
            if ($file) {
                $this->setCacheFile($file->id, $file->md5_value, $file->local_url);
                $data = ['file_id' => $file->id, 'remote_url' => $this->getRemoteUrlAttribute($file->local_url)];
            }
        }
        return $data;
    }

    //文件地址获取器
    public function getRemoteUrlAttribute($value)
    {
      
        $config = config('filesystems.disks.oss');

        if ($value) {
            $http = $config['ssl'] === true ? 'https://' : 'http://';
            if (empty($config['cdnDomain'])) {
                $bucket = $config['bucket'];
                $endpoint = $config['endpoint'];
                return $http . $bucket . '.' . $endpoint . $value;
            } else {
                return $config['cdnDomain'] . $value;
            }
        }
        return '';
    }


}
